using System;
using System.Net.Sockets;
using System.Net;

namespace ICeFramework.Utilities.Sockets
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks></remarks>
    /// <example></example>
    public class ClientSocket : System.ComponentModel.Component
    {
        #region Events

        public event System.EventHandler create;
        public event CloseEvenHandler close;
        public event AcceptEvenetHandler accept;

        #endregion

        #region Private Declarations

        private IAsyncResult m_ar;
        private Socket m_Socket;
        private int m_Port;

        #endregion

        #region public ClientSocket()
        /// <summary>
        /// Initializes a new instance of the <b>ListenSocket</b> class.
        /// </summary>
        public ClientSocket()
        {
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            m_Port = 0;

            this.create += new EventHandler(OnCreate);
            this.accept += new AcceptEvenetHandler(OnAccept);
            this.close += new CloseEvenHandler(OnClose);
        }
        #endregion

        #region public int Port
        /// <summary>
        /// Get/Sets the Port of the ListenSocket
        /// </summary>
        /// <value></value>
        public int Port
        {
            set
            {
                m_Port = value;
            }
            get
            {
                return m_Port;
            }
        }
        #endregion

        #region public Socket SocketHandle
        /// <summary>
        /// Get/Sets the SocketHandle of the ListenSocket
        /// </summary>
        /// <value></value>
        public Socket SocketHandle
        {
            set
            {
                create(this, null);
                m_Socket = value;
            }
            get
            {
                return m_Socket;
            }
        }
        #endregion

        #region public void StartListen(bool IsBlocked)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="IsBlocked"></param>
        public void StartListen(bool IsBlocked)
        {
            create(this, null);
            IPEndPoint ep = new IPEndPoint(IPAddress.Any, m_Port);
            m_Socket.Bind(ep);
            m_Socket.Listen(5);
            if (IsBlocked == false)
                m_Socket.BeginAccept(new AsyncCallback(OnSendEvents), null);

        }
        #endregion

        #region public void StopListen()
        /// <summary>
        /// 
        /// </summary>
        public void StopListen()
        {
            m_Socket.EndAccept(m_ar);
        }
        #endregion

        #region public Socket Accept()
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Socket Accept()
        {
            Socket s = m_Socket.Accept();
            AcceptEventArgs e = new AcceptEventArgs();
            e.m_Socket = s;
            e.m_ar = null;
            accept(this, e);
            return s;
        }
        #endregion

        #region public void Close()
        /// <summary>
        /// 
        /// </summary>
        public void Close()
        {
            CloseEventArgs e = new CloseEventArgs();
            e.create(null, null, "Closed By user");
            close(this, e);
            m_Socket.Close();
        }
        #endregion

        #region private void OnSendEvents(IAsyncResult ar)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ar"></param>
        private void OnSendEvents(IAsyncResult ar)
        {
            if (ar.IsCompleted)
            {
                Socket s = m_Socket.EndAccept(ar);
                AcceptEventArgs e = new AcceptEventArgs();
                e.m_ar = ar;
                m_ar = ar;
                e.m_Socket = s;
                accept(this, e);
                m_Socket.BeginAccept(new AsyncCallback(OnSendEvents), null);
            }
        }
        #endregion

        #region protected void OnCreate(object sender, EventArgs e)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnCreate(object sender, EventArgs e)
        {

        }
        #endregion

        #region protected void OnAccept(object Sender, AcceptEventArgs e)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="e"></param>
        protected void OnAccept(object Sender, AcceptEventArgs e)
        {
        }
        #endregion

        #region protected void OnClose(object Sender, CloseEventArgs e)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="e"></param>
        protected void OnClose(object Sender, CloseEventArgs e)
        {

        }
        #endregion
    }
}
